package top.heue.utils.base.util.file

import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.provider.DocumentsContract
import android.provider.MediaStore
import androidx.activity.ComponentActivity
import androidx.documentfile.provider.DocumentFile
import top.heue.utils.base.helper.SAFHelper
import java.io.*

/**
 * 主要放置saf操作的一些代码，需要打开文件等操作用SAFHelper
 *
 * @see SAFHelper
 */
class SAFUtil(private val context: Context) {
    companion object {
        /**
         * inputStream转string
         */
        fun inputStreamToString(inputStream: InputStream): String {
            val stringBuilder = StringBuilder("")
            inputStream.use { stream ->
                BufferedReader(
                    InputStreamReader(stream)
                ).use { reader ->
                    var line: String?
                    try {
                        while (reader.readLine().also { line = it } != null) {
                            stringBuilder.appendLine(line)
                        }
                    } catch (e: Exception) {
                    }
                }
            }
            return stringBuilder.toString()
        }
    }

    /**
     * 读取，得到输入流，自动关闭，为null就是不存在
     */
    fun inputStream(uri: Uri, run: (InputStream?) -> Unit) {
        val i = context.contentResolver.openInputStream(uri)
        i.use(run)
    }

    /**
     * 写入，得到输出流，自动关闭，null就是没法写
     * @param mode – The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw" or "rwt". SeeParcelFileDescriptor.parseMode for more details
     */
    fun outputStream(uri: Uri, mode: String = "w", run: (OutputStream?) -> Unit) {
        val o = context.contentResolver.openOutputStream(uri, mode)
        o.use(run)
    }

    /**
     * 读取uri文件为string
     */
    fun readFileToString(uri: Uri): String {
        val stream = context.contentResolver.openInputStream(uri) ?: return ""
        return inputStreamToString(stream)
    }

    /**
     * 读取uri文件为stream
     */
    fun readFileToStream(uri: Uri): InputStream? = context.contentResolver.openInputStream(uri)

    /**
     * 复制uri文件到File
     */
    fun copyFile(uri: Uri, file: File): File {
        context.contentResolver.openInputStream(uri).use { inputStream ->
            val bis = BufferedInputStream(inputStream, 16)
            val bos = BufferedOutputStream(FileOutputStream(file, false), 16)
            var size: Int
            val buffer = ByteArray(10240)
            while (bis.read(buffer).also { size = it } != -1) {
                bos.write(buffer, 0, size)
            }
            bos.flush()
            bis.close()
            bos.close()
        }
        return file
    }

    /**
     * 获取文件名称
     */
    fun getFileRealNameFromUri(fileUri: Uri?): String {
        if (fileUri == null) return ""
        val documentFile = DocumentFile.fromSingleUri(context, fileUri) ?: return ""
        return documentFile.name!!
    }

    /** 获取文件路径 */
    fun getFilePath(fileUri: Uri?): String {
        if (fileUri == null) return ""
        var path = ""
        if ("file".equals(fileUri.scheme, ignoreCase = true)) { //使用第三方应用打开
            //String path结果
            path = fileUri.path.toString()
        } else {
            if (DocumentsContract.isDocumentUri(context, fileUri)) {
                val docId = DocumentsContract.getDocumentId(fileUri)
                if ("com.android.providers.media.documents" == fileUri.authority) {
                    val id = docId.split(":").toTypedArray()[1]
                    val selection = MediaStore.Images.Media._ID + "=" + id
                    path = getPath(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        selection
                    )
                } else if ("com.android.providers.downloads.documents" == fileUri.authority) {
                    val contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"),
                        java.lang.Long.valueOf(docId)
                    )
                    path = getPath(contentUri, "")
                }
            } else if ("content".equals(fileUri.scheme, ignoreCase = true)) {
                path = getPath(fileUri, "")
            }
        }
        return path
    }

    private fun getPath(uri: Uri, selection: String): String {
        var path = ""
        val cursor: Cursor =
            context.contentResolver.query(uri, null, selection, null, null)!!
        if (cursor.moveToFirst()) {
            val p = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
            if (p >= 0)
                path = cursor.getString(p)
        }
        cursor.close()
        return path
    }
}